package il.ac.tau.cg.ex3.parser.parametershander;

import il.ac.tau.cg.ex3.entities.scene.Scene;
import il.ac.tau.cg.ex3.entities.styles.Color;
import il.ac.tau.cg.ex3.entities.styles.drawables.ColorDrawable;
import il.ac.tau.cg.ex3.entities.styles.drawables.Drawable;
import il.ac.tau.cg.ex3.entities.styles.drawables.ImageDrawable;
import il.ac.tau.cg.ex3.parser.Parser;
import il.ac.tau.cg.ex3.parser.Parser.ParseException;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class SceneParameterHandler extends EntityParametersHandler
{
	private Color ambientColor;
	private Color backColor;
	private Drawable backDrawable;
	private int superSampleWidth;
	private boolean useAcceleration;	
	
	public SceneParameterHandler()
	{
		super();
		
		ambientColor     = new Color(0.1, 0.1, 0.1);
		backColor		 = new Color(0.0, 0.0, 0.0);
		backDrawable     = new ColorDrawable(backColor.clone());
		superSampleWidth = 1;
		useAcceleration  = false;	
	}
	
	public boolean addParam(String key, String[] value) throws ParseException
	{
		paramsCache.add(key);
		
		ESceneParameter param =  ESceneParameter.findParam(key);
		
		if (param == null)
		{
			return false;
		}
		
		Parser.pAssert((value.length == param.argsNum), param.name + " INVALID ARGS NUM");
		
		switch (param)
		{
			case AMBIENT_LIGHT:
			{
				ambientColor = getColor(value);
			}break;
				
			case BACKGROUND_COLOR:
			{
				backColor = getColor(value);
				backDrawable = new ColorDrawable(backColor.clone());
			}break;
				
			case BACKGROUND_TEX:
			{	
				File srcFile = new File(value[0]);
				
				BufferedImage srcImgBuf = null; 
				try 
				{
					srcImgBuf = ImageIO.read(srcFile);
				}
				catch(IOException e)
				{
					Parser.pAssert(false, "IO EXCEPTION");
				}
				
				backDrawable = new ImageDrawable(srcImgBuf);
			}break;
				
			case SUPER_SAMP_WIDTH:
			{	
				superSampleWidth = Integer.parseInt(value[0]);
			}break;
				
			case USE_ACCELERAION:
			{
				useAcceleration = (Integer.parseInt(value[0]) == 1);
			}break;
		}
		
		return true;
	}
	
	protected void createEntity(Scene scene) throws ParseException
	{
		scene.setBackColor(backColor);
		scene.setBackDrawable(backDrawable);
		scene.setAmbientColor(ambientColor);
		scene.setSuperSampleWidth(superSampleWidth);
		scene.setAccelerated(useAcceleration);
	}

	@Override
	protected boolean validateEntity() throws ParseException
	{
		for (ESceneParameter param : ESceneParameter.values())
		{
			if (param.isMandatory && !paramsCache.contains(param.name))
			{
				return false;
			}
		}
		
		return true;
	}
	
	private enum ESceneParameter 
	{
		/* SCENE ENTITIES */
		BACKGROUND_COLOR ("background-col", false, 3),
		BACKGROUND_TEX   ("background-tex", false, 1),
		AMBIENT_LIGHT    ("ambient-light", false, 3),
		SUPER_SAMP_WIDTH ("super-samp-width", false, 1),
		USE_ACCELERAION  ("use-acceleration", false, 1);
		
		private final String  name;
		private final boolean isMandatory;
		private final int     argsNum;
		
		ESceneParameter(String name, boolean isMandatory, int argsNum)
		{
			this.name = name;
			this.isMandatory = isMandatory;
			this.argsNum = argsNum;
		}
		
		public static ESceneParameter findParam(String name)
		{
			for (ESceneParameter param : ESceneParameter.values())
			{
				if (param.name.equals(name))
				{
					return param;
				}
			}
			
			return null;
		}
	}
}